package com.devo.icecream.ui.diy

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.lifecycle.lifecycleScope
import com.devo.icecream.AppLogger
import com.devo.icecream.AppToast
import com.devo.icecream.IceCreamApp
import com.devo.icecream.data.APIClient
import com.devo.icecream.data.IngredientDto
import com.devo.icecream.data.IngredientsBean
import com.devo.icecream.exception.APIException
import com.devo.icecream.ui.BaseActivity
import com.devo.icecream.ui.order.OrderActivity
import com.devo.icecream.ui.theme.IcecreamTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlin.math.min

typealias  Category = IngredientDto.CategoryBean

class DiyActivity : BaseActivity() {

    private val selectIds = MutableStateFlow(mutableListOf<Int>())

    //成分
    private val ingredients = MutableStateFlow(listOf<IngredientsBean>())
    //菜单 配料
    private val menu = MutableStateFlow(mapOf<String, List<IngredientsBean?>>())
    //类别和菜单的集合
    private val menuMap =
        MutableStateFlow(mapOf<Category, List<IngredientsBean?>>())

    //类别
    private val categories = MutableStateFlow(listOf<Category>())
    //服务电话
    private val servicePhone by lazy {
        IceCreamApp.preferences.getString("service_phone", "") ?: ""
    }
    //菜单总热量
    private val totalPower = MutableStateFlow(0.0)
    //总价格
    private val totalPrice = MutableStateFlow(0.0)
    //倒计时
    private val countdown = MutableStateFlow(120)


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            IcecreamTheme {
                // A surface container using the 'background' color from the theme
                val ingredientList = ingredients.collectAsState()

                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    DiyScreen(
                        countDown = countdown.collectAsState().value,
                        selectIds = selectIds.collectAsState().value,
                        // 转换以 category 为 key 的 map，并排序 category
                        ingredients = ingredientList.value
                            .groupBy { it.categoryId }
                            .entries.map {
                                //类别
                                categories.value.first { c -> c.id == it.key } to it.value }
                            .sortedBy { it.first.sort }
                            .toMap(),
                        menu = menuMap.collectAsState().value
                            .entries.sortedBy { it.key.sort }
                            .associate { it.key to it.value },
                        onSelectItem = { onSelectItem(it) },
                        servicePhone = servicePhone,
                        totalPower = totalPower.collectAsState().value,
                        totalPrice = totalPrice.collectAsState().value,
                        onBack = {
                            finish()
                        },
                        // 清空整个菜单
                        onMenuClear = {
                            selectIds.tryEmit(mutableListOf())
                            buildEmptyMenu(ingredientList.value)
                        },
                        // 移除单个食材
                        onRemove = {
                            selectIds.tryEmit(
                                selectIds.value.toMutableList().apply {
                                    remove(it)
                                }
                            )
                        },
                        onConfirm = {
                            onConfirm()
                        }
                    )
                }
            }
        }
    }

    /**
     * 添加选中食材Id
     * @param id Int
     */
    private fun onSelectItem(id: Int) {
        val list = selectIds.value.toMutableList()
        val item = ingredients.value.first { it.id == id }
        val allowInsert = menu.value[item.categoryName]?.let { ls ->
            ls.count { null == it } > 0
        } ?: false
        val count = list.count { it == id }

        // 允许添加
        if (((count < 2 && item.allowRepeat) || count <= 0) && allowInsert) {
            // 普通食材只能添加一次，重复食材只能添加两次
            list.add(id)
            selectIds.tryEmit(list.toMutableList())
        } else if (!allowInsert && (count == 1 && item.allowRepeat)) {
            // 不允许添加的情况下，只有已添加的可重复食材可以添加
            list.add(id)
            selectIds.tryEmit(list.toMutableList())
        }

        AppLogger.i("${selectIds.value}")
    }

    /**
     * 使用食材列表，构建空菜单
     * @param ingredients List<IngredientsBean>
     */
    private fun buildEmptyMenu(ingredients: List<IngredientsBean>) {
        menu.tryEmit(
            ingredients.let { list ->
                val map = list.groupBy { it.categoryName }

                map.map { entry ->
                    val (key, value) = entry
                    val size = value.size
                    //类别
                    val limit = categories.value.firstOrNull { it.name == key }?.chooseNum ?: size

                    val length = min(size, limit)
                    key to (0 until length).map { null }.toMutableList()
                }

            }.toMap()
        )
    }

    private fun onConfirm() {
        if (checkMenu()) {

            menu.value.values.flatten().filterNotNull().takeIf { it.isNotEmpty() }?.let {
                OrderActivity.goActivity(this, isDiy = true, ingredients = it)
                finish()
            }


        }
    }

    private fun checkMenu(): Boolean {
        return menuMap.value.all { entry ->
            val (category, list) = entry
            return@all if (category.isMust == 1 && list.filterNotNull().isEmpty()) {
                AppToast.show("${category.name}中至少选择一项")
                false
            } else {
                true
            }
        }

    }

    override fun onStart() {
        super.onStart()
        lifecycleScope.launch {
            launch {
                //类别
                categories.collectLatest { list ->
                    list.takeIf { it.isNotEmpty() }?.let { ls ->
                        menuMap.tryEmit(
                            menu.value
                                .map { entry ->
                                    ls.first { it.name == entry.key } to entry.value
                                }
                                .toMap()
                        )
                    }
                }
            }
            launch {
                menu.collectLatest { m ->
                    // 类别 转换为UI显示数据
                    categories.value.takeIf { it.isNotEmpty() }?.let { ls ->
                        menuMap.tryEmit(
                            m.map { entry ->
                                ls.first { it.name == entry.key } to entry.value
                            }
                                .sortedBy { -it.first.sort }
                                .toMap()
                        )
                    }

                }
            }
            // 请求食材列表
            launch {
                try {
                    val dto = APIClient.getIngredients()
                    // 类别 由于逻辑问题。categories 必须在 ingredients 之前更新
                    categories.tryEmit(dto?.categoryList ?: listOf())
                    ingredients.tryEmit(dto?.ingredients ?: listOf())
                } catch (e: APIException) {
                    AppLogger.e(e, "拉取食材列表报错！")
                }
            }
            // 根据食材列表构建空菜单
            launch {
                ingredients.collectLatest { list ->
                    buildEmptyMenu(list)
                }
            }
            // 倒计时协程
            launch {
                while (countdown.value > 0) {
                    delay(1_000)
                    countdown.tryEmit(countdown.value - 1)
                }
            }
            // 倒计时结束返回首页
            launch {
                countdown.collectLatest {
                    if (it <= 0) {
                        finish()
                    }
                }
            }
            // 监听选中食材，构建新菜单
            launch {
                selectIds.collectLatest { list ->

                    // 将选中食材ID以类目名分类
                    val maps = list
                        .map { i -> ingredients.value.first { it.id == i } }
                        .groupBy { it.categoryName }
                        .map { entry ->
                            val (k, v) = entry
                            k to v.map {
                                it.chose = v.count { x -> x.id == it.id }
                                it
                            }.distinctBy { a -> a.id }
                        }
                        .toMap()


                    menu.tryEmit(
                        menu.value.let {
                            val ms = it.toMutableMap()
                            // 遍历菜单，在相同下标位置插入新食材，其余位置为null，保持类目下列表长度不变
                            ms.map { entry ->
                                val (key, vs) = entry
                                val newVs = maps[key] ?: listOf()

                                key to vs.mapIndexed { index, _ ->
                                    if (index < newVs.size) newVs[index] else null
                                }
                            }
                        }.toMap()
                    )

                    val m = menu.value
                    // 计算总热量
                    totalPower.tryEmit(
                        m.values.toList().sumOf { ls ->
                            ls.filterNotNull().sumOf { c -> c.chose * c.power }
                        }
                    )
                    // 计算总价格
                    totalPrice.tryEmit(
                        m.values.toList().sumOf { ls ->
                            ls.filterNotNull().sumOf { c -> c.chose * c.price.toDouble() }
                        }
                    )

                }
            }
        }
    }

}
